home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / dskut / qic02_11.zip / QIC02.C < prev    next >
C/C++ Source or Header  |  1993-05-28  |  31KB  |  1,084 lines

  1. /* WARNING WARNING WARNING WARNING WARNING
  2.  *
  3.  * This is the MSDOS device driver code for Archive SC402 / SC499R
  4.  * QIC02 tape controllers.
  5.  * 
  6.  * This code is BETA and is known to have:
  7.  *
  8.  * - BUGS (there *has* to be at least one :-)
  9.  * - code 'stolen' from H.H. Bergman's QIC02 device driver for
  10.  *   Linux-386, Doug Braun's SCSI driver, TCDEV.ARC (from Simtel20)
  11.  * - lack of documentation
  12.  * - dirty code
  13.  *
  14.  * This code is dangerous, not only when running but also when looking
  15.  * at it: it is 100% HACKwork (TM) and the result of a hardware guy trying
  16.  * to write software. Perhaps it will work, perhaps not.
  17.  *
  18.  * NEVER use this code to do anything serious like dumping / restoring
  19.  * important data :-)
  20.  *
  21.  * History:
  22.  *
  23.  * 0.0 - initial 'working' version
  24.  * 0.1 - internal
  25.  *       fixed the 'can only write slowly' bug:
  26.  *       fixed read_status & dma_wait routine
  27.  * 0.2 - internal
  28.  *       cleaned up code
  29.  *       changed device name from TAPE to TAPE$
  30.  *       removed printf's to reduce code size
  31.  *       fixed some suspicious pointer conversions
  32.  * 0.3 - limited release
  33.  *       removed alloc mem on 64K DMA wrap since it didn't work
  34.  * 0.4 - added info returned for mt status, e.g. error count
  35.  * 1.0 - ready for public release (at last...)
  36.  * 1.1 - no change to QIC02.C but needed to patch TCDEV.OBJ to already
  37.  *       have the device driver attributes properly set in order to
  38.  *       get things going with an OS/2 DOS box.
  39.  *
  40.  *
  41.  * Eddy Olk
  42.  * email: eddy@duteca.et.tudelft.nl
  43.  *
  44.  *
  45.  * Oh, almost forgot:
  46.  *
  47.  * QIC02 tape device driver for MSDOS
  48.  * Copyright (C) 1993  Eddy Olk
  49.  *
  50.  * This program is free software; you can redistribute it and/or modify
  51.  * it under the terms of the GNU General Public License as published by
  52.  * the Free Software Foundation; either version 2 of the License, or (at
  53.  * your option) any later version.
  54.  *
  55.  * This program is distributed in the hope that it will be useful, but
  56.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  57.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  58.  * General Public License for more details.
  59.  *
  60.  * You should have received a copy of the GNU General Public License
  61.  * along with this library; if not, write to the Free Software
  62.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  63.  *
  64.  */
  65.  
  66. #include <dos.h>
  67. #include <string.h>
  68. #include <mem.h>
  69. #include <ctype.h>
  70.  
  71. #include "mtio.h"
  72. #include "qic02.h"
  73.  
  74. int errno;                      /* to keep the linker happy */
  75.  
  76. int iobase = 0x220;             /* default IObase = 0x220h */
  77. int dmanr = 3;                  /* default DMA channel = 3 */
  78. int intnr = 7;                  /* default IRQ number = 7 */
  79.                                 /* (currently not used) */
  80.  
  81. #define DUMMY iobase+3          /* dummy I/O port for reading */
  82.                                 /* used to get some sort of CPU */
  83.                                 /* independant minimum time */
  84.  
  85. #define VERSION "1.1"
  86. #define DEVICENAME "TAPE$   "
  87.  
  88. struct srh {
  89.         char len;
  90.         char unit;
  91.         char cmd;
  92.         int status;
  93.         char res[8];
  94.         union {
  95.                 struct { /* init */
  96.                         char units;
  97.                         char far *kaddr;
  98.                         char far *baddr;
  99.                 } cin;
  100.                 struct { /* media check */
  101.                         char media, stat;
  102.                 } cmc;
  103.                 struct { /* build parameter block. */
  104.                         char media;
  105.                         char far *taddr;
  106.                         char far *baddr;
  107.                 } cbpb;
  108.                 struct { /* reading and writing */
  109.                         char media;
  110.                         char far *taddr;
  111.                         unsigned count;
  112.                         unsigned start;
  113.                 } crw;
  114.                 struct { /* nondestructive read no wait */
  115.                         char ch;
  116.                 } cic;
  117.         } c;
  118. };
  119.  
  120. extern char dev_name[9];
  121. extern int dev_attr;
  122.  
  123. #ifdef USE_PRINTF
  124. char msg[100];
  125. #endif
  126.  
  127. char buffer[1024];              /* emergency buffer */
  128. char far *abuf;                 /* non 64K crossing 512 byte emergency */
  129. char far *buf;
  130. char far *bufptr;
  131.  
  132.  
  133. static char device_open;
  134. static char bytes_transferred;
  135. static char readmode;
  136. static unsigned error_count;
  137. static unsigned underrun_count;
  138. static long fileno = 0;
  139. static long blkno = 0;
  140. static char move_dir = 1;
  141.  
  142. /* variables for tape status */
  143. static unsigned char statusbyte[6];
  144.  
  145. /* variables for DMA stuff */
  146. static char far *dptr;
  147. static unsigned dlen;
  148. static unsigned adlen;
  149. static char rwflag;
  150. static unsigned dma_residue;
  151.  
  152. biosputs(s)
  153. char *s;
  154. {
  155.   static char c;
  156.   static int oldbp;
  157.  
  158.   while (*s) {
  159.     c = *s++;
  160.     if (c == '\n') {
  161.       oldbp = _BP;
  162.       _AL = '\r';
  163.       _AH = 0x0e;
  164.       _BH = 0;
  165.       geninterrupt(0x10);
  166.       _BP = oldbp;
  167.     }
  168.  
  169.     oldbp = _BP;
  170.     _AL = c;
  171.     _AH = 0x0e;
  172.     _BH = 0;
  173.     geninterrupt(0x10);
  174.     _BP = oldbp;
  175.   }
  176. }
  177.  
  178.  
  179. /* Find out 14 possible exceptions, got these from the Archive docs */
  180. int get_qicerror()
  181. {
  182.   if (errstat(1,ST1)) {
  183.     if (errstat(1,PAR)) {
  184.       if (errstat(0,ST0) && errstat(0,UDE)) {
  185.         return THCerr;          /* 14: Throughcheck error. FATAL on */
  186.                                 /* write, CONTINUABLE on read */
  187.       }
  188.       else {
  189.         return PARerr;          /* 13: bus parity error. CONTINUABLE */
  190.       }
  191.     }
  192.     if (errstat(1,POR))         /* 11: Reset occured. FATAL */
  193.       return PORerr;
  194.     if (errstat(1,ILL))         /* 10: Illegal command. FATAL */
  195.       return ILLerr;
  196.     if (errstat(1,MBD)) {
  197.       if (errstat(0,ST0) && errstat(0,FIL))
  198.           return MARerr;        /* 12: Marginal block. CONTINUABLE */
  199.     }
  200.     if (errstat(1,EOD)) {
  201.       if (errstat(0,ST0) && errstat(0,EOM)) {
  202.         return EDMerr;  /* 8: End of data & EOM. CONTINUABLE */
  203.       }
  204.       else {
  205.         return EODerr;  /* 7: End of data. CONTINUABLE */
  206.       }
  207.     }
  208.   }
  209.   if (errstat(0,ST0)) {
  210.     if (errstat(0,FIL))
  211.       return RFMerr;            /* 9: Read file mark. CONTINUABLE */
  212.     if (errstat(0,UDE)) {
  213.       if (errstat(1,ST1) && errstat(1,BOM)) {
  214.         return RWAerr;          /* 4: Read or write abort. FATAL */
  215.       }
  216.       else {
  217.         if (errstat(0,BNL)) {
  218.           return RFBerr;        /* 6: Read error, filler block. */
  219.                                 /* CONTINUABLE */
  220.         }
  221.         else {
  222.           return RBBerr;        /* 5: Read error, bad block. */
  223.                                 /* CONTINUABLE */
  224.         }
  225.       }
  226.     }
  227.     if (errstat(0,EOM))
  228.       return EOMerr;            /* 3: End Of Media. CONTINUABLE */
  229.     if (errstat(0,CNI))
  230.       return CNIerr;            /* 1: Cartridge not in place. FATAL */
  231.     if (errstat(0,WRP))
  232.       return WRPerr;            /* 2: Write protected cartridge. FATAL */
  233.   }
  234.   return 0;                     /* 0: No errors? Hope we didn't miss one */
  235. }
  236.   
  237. void wait_more_than_usec(int delay)
  238. {
  239.   int i;
  240.   for (i=0; i<delay; i++) {
  241.     inportb(DUMMY);
  242.     inportb(DUMMY);
  243.   }
  244. }
  245.  
  246. int read_status()
  247. {
  248.   int i;
  249.  
  250.   wait_stat;                    /* wait for ready or exception */
  251.   outdata(RDSTATUS);            /* write read status command */
  252.   setreq;                       /* set request */
  253.   wait_rdy;                     /* wait for ready, ignore possible */
  254.                                 /* still active exception */
  255.   disable();
  256.   resetreq;                     /* reset request */
  257.   wait_nrdy;                    /* wait until ready is (has been) inactive */
  258.   enable();
  259.   while (!(inportb(STATUS) & DIRC)); /* wait for data direction change */
  260.   for (i=0; i<6; i++) {
  261.     wait_stat;                  /* wait for ready, don't hope for exceptions */
  262.     if (is_exception) {
  263.       return DEADerr;           /* unexpected exception, tape drive */
  264.                                 /* must be dead */
  265.     }
  266.     statusbyte[i] = indata;     /* get status byte [i] */
  267.     setre